package com.sunflower.common.core.interceptor;

import cn.hutool.core.util.StrUtil;
import com.sunflower.common.core.constant.CacheConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.interceptor.KeyGenerator;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * @Classname CombinationKeyGenerator
 * @Author: sunluquan
 * @Description TODO
 */
@Slf4j
public class CombinationKeyGenerator {

    /**
     * 获取缓存key生成器
     *
     * @param prefix key前缀
     * @return
     */
    public static KeyGenerator getKeyGeneratorForCacheable(String prefix) {
        return new KeyGeneratorForCacheable(prefix);
    }

    public static KeyGenerator getKeyGeneratorForCacheable() {
        return new KeyGeneratorForCacheable();
    }

    /**
     * 删除缓存key生成器
     *
     * @param prefix key前缀
     * @return
     */
    public static KeyGenerator getKeyGeneratorForEvict(String prefix) {
        return new KeyGeneratorForEvict(prefix);
    }

    public static KeyGenerator getKeyGeneratorForEvict() {
        return new KeyGeneratorForEvict();
    }

    private static abstract class AbstractKeyGenerator implements KeyGenerator {
        private String prefix;

        public AbstractKeyGenerator(String prefix) {
            this.prefix = prefix;
        }

        public AbstractKeyGenerator() {
        }

        public StringBuilder builderPrefix() {
            if (StrUtil.isNotEmpty(prefix)) {
                return new StringBuilder(prefix).append(getDelimiter());
            }
            return new StringBuilder();
        }

        public String getDelimiter() {
            return StrUtil.COLON;
        }
    }

    /**
     * 生成查询key 的生成器
     */
    public static class KeyGeneratorForCacheable extends AbstractKeyGenerator {

        public KeyGeneratorForCacheable(String prefix) {
            super(prefix);
        }

        public KeyGeneratorForCacheable() {
        }

        @Override
        public Object generate(Object target, Method method, Object... params) {
            StringBuilder strBuilder = builderPrefix().append(target.getClass().getSimpleName())
                .append(getDelimiter()).append(method.getName());
            if (params != null) strBuilder.append(getDelimiter()).append(Arrays.hashCode(params));

            String key = strBuilder.toString();

            log.info("{}-generate key for cache- :{}", this, key);
            return key;
        }
    }

    /**
     * 生成删除key的生成器
     */
    public static class KeyGeneratorForEvict extends AbstractKeyGenerator {
        public KeyGeneratorForEvict(String prefix) {
            super(prefix);
        }

        public KeyGeneratorForEvict() {
        }

        @Override
        public Object generate(Object target, Method method, Object... params) {
            String key = builderPrefix().append(target.getClass().getSimpleName()).append(CacheConstants.ASTERISK).toString();
            log.info("{}-generate key for evict- :{}", this, key);
            return key;
        }
    }
}
